package entities.concept;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import option.KBVocabulary;

import utils.Display;

import entities.Individual;
import entities.KBEntity;

//provided as an alternative way to access instances
public final class Nominal extends AtomicConcept {
	private final String nominalId;
	private Set<Individual> nomInNodes;
	private Individual nomItp; // a single node presents this nominal
	private static Map<String, Nominal> nominalMaps = new HashMap<String, Nominal>();
	private static Set<Nominal> usedNominals = new HashSet<Nominal>();

	private Nominal(String nom) {
		this.nominalId = nom;
		this.nomInNodes = new HashSet<Individual>();
	}

	public static void clearNominalMap() {
		nominalMaps.clear();
	}

	public static Map<String, Nominal> getNominalMaps() {
		return nominalMaps;
	}

	public static Collection<Nominal> getAllNominals() {
		return nominalMaps.values();
	}

	public void intepretNominal(Individual n) {
		this.nomItp = n;
	}

	public Individual getAttachedInstanceForExistsRule() {
		if (this.nomItp == null) {
			Individual anon = Individual.getAnonIndividual();
			// anon.addLabels(this);
			this.nomItp = anon;
		}
		usedNominals.add(this);
		return this.nomItp;
	}

	public static Set<Nominal> getReasonedNominals() {
		return usedNominals;
	}

	public static void clearReasonedNominals() {
		usedNominals.clear();
	}

	public static Nominal getNominal(String nom, boolean reasoningInProgress) {
		Nominal n = null;
		if (nominalMaps.containsKey(nom)) {
			n = nominalMaps.get(nom);
		} else {
			n = new Nominal(nom);
			nominalMaps.put(nom, n);
		}
		if (reasoningInProgress) {
			usedNominals.add(n);
		}
		return n;
	}

	public Set<Individual> appearInNodes() {
		return this.nomInNodes;
	}

	public boolean removeAttachedIndividual(Individual n) {
		return this.nomInNodes.remove(n);
	}

	public boolean addAttachedIndividual(Individual n) {
		return this.nomInNodes.add(n);
	}

	public String getName() {
		return this.nominalId;
	}

	@Override
	public Concept getPrimeCopy() {
		return Nominal.getNominal(this.nominalId + PRIME, false);
	}

	@Override
	public String toString() {
		String cont = this.nominalId;
		// String[] prefix ={
		// "http://www.lehigh.edu/~zhp2/2004/0401/univ-bench.owl#",
		// "http://www.Department0.University0.edu/"
		// };
		// for(String p:prefix){
		// if(cont.contains(p)){
		// cont = cont.replaceAll(p, "");
		// }
		// }
		return Display.NOMINAL_LEFT_SIGN + cont + Display.NOMINAL_RIGHT_SIGN;
	}

	@Override
	public String toSerializedString() {
		return " (" + KBVocabulary.NOMINAL + " " + this.nominalId + ") ";
	}

	private volatile int hashCode = 0;

	@Override
	public int hashCode() {
		if (hashCode != 0) {
			return hashCode;
		}
		final int prime = 31;
		int result = 29;
		result = prime * result
				+ ((nominalId == null) ? 0 : nominalId.hashCode());
		hashCode = result;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Nominal))
			return false;
		Nominal other = (Nominal) obj;
		// if (nomInNodes == null) {
		// if (other.nomInNodes != null)
		// return false;
		// } else if (!nomInNodes.equals(other.nomInNodes))
		// return false;
		if (nominalId == null) {
			if (other.nominalId != null)
				return false;
		} else if (!nominalId.equals(other.nominalId))
			return false;
		return true;
	}

	@Override 
	public Set<KBEntity> extractSig(){
		Set<KBEntity> sig = new HashSet<KBEntity>();
		return sig;
	}

}
